features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &options.flag_package,
+ spec: ops::Packages::Packages(&options.flag_package),
release: true,
mode: ops::CompileMode::Bench,
filter: ops::CompileFilter::new(options.flag_lib,
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &options.flag_package,
+ spec: ops::Packages::Packages(&options.flag_package),
mode: ops::CompileMode::Build,
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,
use cargo::core::Workspace;
-use cargo::ops::{self, MessageFormat};
+use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &options.flag_package,
+ spec: Packages::Packages(&options.flag_package),
filter: ops::CompileFilter::new(options.flag_lib,
&options.flag_bin,
&empty,
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &[],
+ spec: ops::Packages::Packages(&[]),
mode: ops::CompileMode::Build,
release: !options.flag_debug,
filter: ops::CompileFilter::new(false, &options.flag_bin, &[],
use cargo::core::Workspace;
-use cargo::ops::{self, MessageFormat};
+use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Config, Human};
use cargo::util::important_paths::{find_root_manifest_for_wd};
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &[],
+ spec: Packages::Packages(&[]),
release: options.flag_release,
mode: ops::CompileMode::Build,
filter: if examples.is_empty() && bins.is_empty() {
use std::env;
use cargo::core::Workspace;
-use cargo::ops::{self, CompileOptions, CompileMode, MessageFormat};
+use cargo::ops::{self, CompileOptions, CompileMode, MessageFormat, Packages};
use cargo::util::important_paths::{find_root_manifest_for_wd};
use cargo::util::{CliResult, CliError, Config, human};
}
};
+ let spec = options.flag_package.map_or_else(Vec::new, |s| vec![s]);
+
let opts = CompileOptions {
config: config,
jobs: options.flag_jobs,
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &options.flag_package.map_or(Vec::new(), |s| vec![s]),
+ spec: Packages::Packages(&spec),
mode: mode,
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,
use cargo::core::Workspace;
-use cargo::ops::{self, MessageFormat};
+use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
let root = find_root_manifest_for_wd(options.flag_manifest_path,
config.cwd())?;
+ let spec = options.flag_package.map_or_else(Vec::new, |s| vec![s]);
+
let doc_opts = ops::DocOptions {
open_result: options.flag_open,
compile_opts: ops::CompileOptions {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &options.flag_package.map_or(Vec::new(), |s| vec![s]),
+ spec: Packages::Packages(&spec),
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,
&options.flag_bin,
use cargo::core::Workspace;
-use cargo::ops::{self, MessageFormat};
+use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Human, human, Config};
-use cargo::util::important_paths::{find_root_manifest_for_wd};
+use cargo::util::important_paths::find_root_manifest_for_wd;
#[derive(RustcDecodable)]
pub struct Options {
flag_no_fail_fast: bool,
flag_frozen: bool,
flag_locked: bool,
+ flag_all: bool,
}
pub const USAGE: &'static str = "
--bench NAME Test only the specified benchmark target
--no-run Compile, but don't run tests
-p SPEC, --package SPEC ... Package to run tests for
+ --all Test all packages in the workspace
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
--release Build artifacts in release mode, with optimizations
--features FEATURES Space-separated list of features to also build
current package is tested. For more information on SPEC and its format, see the
`cargo help pkgid` command.
+All packages in the workspace are tested if the `--all` flag is supplied. The
+`--all` flag may be supplied in the presence of a virtual manifest.
+
The --jobs argument affects the building of the test executable but does
not affect how many jobs are used when running the tests.
&options.flag_bench);
}
+ let spec = if options.flag_all {
+ Packages::All
+ } else {
+ Packages::Packages(&options.flag_package)
+ };
+
let ops = ops::TestOptions {
no_run: options.flag_no_run,
no_fail_fast: options.flag_no_fail_fast,
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
- spec: &options.flag_package,
+ spec: spec,
release: options.flag_release,
mode: mode,
filter: filter,
Some(err) => {
Err(match err.exit.as_ref().and_then(|e| e.code()) {
Some(i) => CliError::new(human("test failed"), i),
- None => CliError::new(Box::new(Human(err)), 101)
+ None => CliError::new(Box::new(Human(err)), 101),
})
}
}
//! previously compiled dependency
//!
+use std::borrow::Cow;
use std::collections::HashMap;
use std::path::PathBuf;
pub all_features: bool,
/// Flag if the default feature should be built for the root package
pub no_default_features: bool,
- /// Root package to build (if None it's the current one)
- pub spec: &'a [String],
+ /// Root package to build (if empty it's the current one)
+ pub spec: Packages<'a>,
/// Filter to apply to the root package to select which targets will be
/// built.
pub filter: CompileFilter<'a>,
Json
}
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum Packages<'a> {
+ All,
+ Packages(&'a [String]),
+}
+
pub enum CompileFilter<'a> {
Everything,
Only {
pub fn compile<'a>(ws: &Workspace<'a>, options: &CompileOptions<'a>)
-> CargoResult<ops::Compilation<'a>> {
- for key in ws.current()?.manifest().warnings().iter() {
- options.config.shell().warn(key)?
+ if let Some(root_package) = ws.current_opt() {
+ for key in root_package.manifest().warnings().iter() {
+ options.config.shell().warn(key)?
+ }
}
compile_ws(ws, None, options)
}
let mut registry = PackageRegistry::new(ws.config())?;
if let Some(source) = source {
- registry.add_preloaded(ws.current()?.package_id().source_id(),
- source);
+ if let Some(root_package) = ws.current_opt() {
+ registry.add_preloaded(root_package.package_id().source_id(), source);
+ }
}
// First, resolve the root_package's *listed* dependencies, as well as
source: Option<Box<Source + 'a>>,
options: &CompileOptions<'a>)
-> CargoResult<ops::Compilation<'a>> {
- let root_package = ws.current()?;
let CompileOptions { config, jobs, target, spec, features,
all_features, no_default_features,
release, mode, message_format,
bail!("jobs must be at least 1")
}
+ let spec: Cow<'a, [String]> = match spec {
+ Packages::Packages(spec) => spec.into(),
+ Packages::All => ws.members()
+ .map(|package| {
+ let package_id = package.package_id();
+ PackageIdSpec::from_package_id(package_id).to_string()
+ })
+ .collect()
+ };
+
let profiles = ws.profiles();
if spec.len() == 0 {
+ let root_package = ws.current()?;
generate_targets(root_package, profiles, mode, filter, release)?;
}
let mut pkgids = Vec::new();
if spec.len() > 0 {
- for p in spec {
+ for p in spec.iter() {
pkgids.push(resolve_with_overrides.query(&p)?);
}
} else {
+ let root_package = ws.current()?;
pkgids.push(root_package.package_id());
};
pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> {
let package = ws.current()?;
+ let spec = match options.compile_opts.spec {
+ ops::Packages::Packages(packages) => packages,
+ _ => {
+ // This should not happen, because the `doc` binary is hard-coded to pass
+ // the `Packages::Packages` variant.
+ bail!("`cargo doc` does not support the `--all` flag")
+ },
+ };
+
let mut lib_names = HashSet::new();
let mut bin_names = HashSet::new();
- if options.compile_opts.spec.is_empty() {
+ if spec.is_empty() {
for target in package.targets().iter().filter(|t| t.documented()) {
if target.is_lib() {
assert!(lib_names.insert(target.crate_name()));
ops::compile(ws, &options.compile_opts)?;
if options.open_result {
- let name = if options.compile_opts.spec.len() > 1 {
+ let name = if spec.len() > 1 {
bail!("Passing multiple packages and `open` is not supported")
- } else if options.compile_opts.spec.len() == 1 {
- PackageIdSpec::parse(&options.compile_opts.spec[0])?
+ } else if spec.len() == 1 {
+ PackageIdSpec::parse(&spec[0])?
.name()
.replace("-", "_")
} else {
features: &[],
no_default_features: false,
all_features: false,
- spec: &[],
+ spec: ops::Packages::Packages(&[]),
filter: ops::CompileFilter::Everything,
release: false,
message_format: ops::MessageFormat::Human,
pub struct Context<'a, 'cfg: 'a> {
pub config: &'cfg Config,
pub resolve: &'a Resolve,
- pub current_package: PackageId,
+ pub current_package: Option<PackageId>,
pub compilation: Compilation<'cfg>,
pub packages: &'a PackageSet<'cfg>,
pub build_state: Arc<BuildState>,
None => None,
};
- let current_package = ws.current()?.package_id().clone();
+ let current_package = ws.current_opt().map(Package::package_id).cloned();
Ok(Context {
host: host_layout,
target: target_layout,
// we don't want to link it up.
if src_dir.ends_with("deps") {
// Don't lift up library dependencies
- if unit.pkg.package_id() != &self.current_package && !unit.target.is_bin() {
+ if self.current_package.as_ref().map_or(false, |p| unit.pkg.package_id() != p)
+ && !unit.target.is_bin() {
None
} else {
Some((
}
pub fn show_warnings(&self, pkg: &PackageId) -> bool {
- pkg == &self.current_package || pkg.source_id().is_path() ||
- self.config.extra_verbose()
+ self.current_package.as_ref().map_or(false, |p| *pkg == *p)
+ || pkg.source_id().is_path()
+ || self.config.extra_verbose()
}
}
}
let build_type = if self.is_release { "release" } else { "debug" };
- let profile = cx.lib_profile(&cx.current_package);
+ let profile = cx.current_package.as_ref().map_or_else(Profile::default, |p| {
+ cx.lib_profile(p).to_owned()
+ });
let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" }
else { "optimized" });
if profile.debuginfo {
let prefer_dynamic = (unit.target.for_host() &&
!unit.target.is_custom_build()) ||
(crate_types.contains(&"dylib") &&
- unit.pkg.package_id() != &cx.current_package);
+ cx.current_package.as_ref().map_or(false, |p| {
+ *p != *unit.pkg.package_id()
+ }));
if prefer_dynamic {
cmd.arg("-C").arg("prefer-dynamic");
}
pub use self::cargo_clean::{clean, CleanOptions};
pub use self::cargo_compile::{compile, compile_ws, resolve_dependencies, CompileOptions};
-pub use self::cargo_compile::{CompileFilter, CompileMode, MessageFormat};
+pub use self::cargo_compile::{CompileFilter, CompileMode, MessageFormat, Packages};
pub use self::cargo_read_manifest::{read_manifest,read_package,read_packages};
pub use self::cargo_rustc::{compile_targets, Compilation, Kind, Unit};
pub use self::cargo_rustc::Context;
use cargotest::{sleep_ms, is_nightly};
use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest};
use cargotest::support::paths::CargoPathExt;
+use cargotest::support::registry::Package;
use hamcrest::{assert_that, existing_file, is_not};
use cargo::util::process;
.arg("--features").arg("foo"),
execs().with_status(0));
}
+
+#[test]
+fn test_all_workspace() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", r#"
+ #[test]
+ fn foo_test() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[test]
+ fn bar_test() {}
+ "#);
+ p.build();
+
+ assert_that(p.cargo_process("test")
+ .arg("--all"),
+ execs().with_stdout_contains("\
+running 1 test
+test foo_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+")
+ .with_stdout_contains("\
+running 1 test
+test bar_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+"));
+}
+
+#[test]
+fn test_all_virtual_manifest() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a", "b"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ #[test]
+ fn a() {}
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.1.0"
+ "#)
+ .file("b/src/lib.rs", r#"
+ #[test]
+ fn b() {}
+ "#);
+ p.build();
+
+ assert_that(p.cargo_process("test")
+ .arg("--all"),
+ execs().with_stdout_contains("\
+running 1 test
+test b ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+")
+ .with_stdout_contains("\
+running 1 test
+test b ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+"));
+}
+
+#[test]
+fn test_all_member_dependency_same_name() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ #[test]
+ fn a() {}
+ "#);
+ p.build();
+
+ Package::new("a", "0.1.0").publish();
+
+ assert_that(p.cargo_process("test")
+ .arg("--all"),
+ execs().with_stdout_contains("\
+running 1 test
+test a ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+"));
+}